#!/bin/bash

TOP_DIR=$(dirname $(readlink -f "$0"))
# KERNEL_DIR=${TOP_DIR}/kernel/kernel/kernel
SIGN_TOOL_DIR=${TOP_DIR}/tools/signtool
OUTPUT_DIR=${TOP_DIR}/../../
HEADER_VERSION="0.0.0.0.0"
# SCRIPTS_DIR=${TOP_DIR}/scripts

function usage ()
{
	echo "[Usage]: "
	# printf "%-50s%-50s\n" "	./build.sh clean"           "#build clean"
	# printf "%-50s%-50s\n" "	./build.sh kernel"          "#build kernel for Euler"
    # printf "%-50s%-50s\n" "	./build.sh rtKernel"        "#build kernel for openEuler-SP1"
	# printf "%-50s%-50s\n" "	./build.sh dtb"             "#build dtb"
	# printf "%-50s%-50s\n" "	./build.sh usrBaseConfig"   "#build usrBaseConfig"
    # printf "%-50s%-50s\n" "	./build.sh hboot2"          "#build hboot2"
	# printf "%-50s%-50s\n" "	./build.sh driver"          "#build driver"
    # printf "%-50s%-50s\n" "	./build.sh kernelSource"    "#build kernelSource"
	# printf "%-50s%-50s\n" "	./build.sh repack"          "#build repack"
    printf "%-50s%-50s\n" "	./build.sh starryos"          "#build starryos"
	exit
}

# function gen_kernel_image()
# {
#     cd $KERNEL_DIR
#     echo "start make kernel......."
#     rm -rf out
#     cp kbuild/* ./ -r

#     #打内核补丁
#     bash mksource.sh

#     #内核编译依赖
#     cp -r ../../libc_sec .
#     cp -r spmi_hisi out
#     cp publickey/ELF_Common_RSA4096_CN_20191009_Huawei.der out/linux-4.19/certs/ELF_Common_RSA4096_CN_20191009_Huawei.der

#     #编译kernel
#     cd out/linux*

#     #打emmc patch
#     patch -E -Rp1 --no-backup-if-mismatch -i $KERNEL_DIR/patches/hisi/0001-ascend-add-emmc-patch-for-mini.patch
#     patch -E -p1 --no-backup-if-mismatch -i $KERNEL_DIR/patches/hisi/0001-ascend-add-emmc-patch-for-ascend-310B.patch

#     #生成内核配置
#     make ARCH=arm64 CROSS_COMPILE=aarch64-target-linux-gnu- ascend310B_defconfig
#     #支持用户自定义内核配置选项，交互式弹出菜单选项
#     make ARCH=arm64 CROSS_COMPILE=aarch64-target-linux-gnu- menuconfig

#     #编译内核
#     make ARCH=arm64 CROSS_COMPILE=aarch64-target-linux-gnu- Image -j16
#     make ARCH=arm64 CROSS_COMPILE=aarch64-target-linux-gnu- modules -j16
#     make ARCH=arm64 CROSS_COMPILE=aarch64-target-linux-gnu- INSTALL_MOD_PATH=$OUTPUT_DIR/modules modules_install
#     mkdir -p $OUTPUT_DIR/kernel_modules
#     find $OUTPUT_DIR/modules/ -name *.ko -exec cp -a {} $OUTPUT_DIR/kernel_modules \;

#     cp -f ${KERNEL_DIR}/out/linux*/arch/arm64/boot/Image $OUTPUT_DIR
#     echo "generate ${OUTPUT_DIR}/kernel_modules success!"
#     echo "generate ${OUTPUT_DIR}/Image success!"
# }

# function gen_dtimage()
# {
#     echo "start generate dt.img......."
#     cd ${TOP_DIR}/dtb/dtbtool
#     sed -i 's/\/tools\/customize/\/dtb/g' CMakeLists.txt
#     rm -rf tmp
#     mkdir tmp
#     cd tmp

#     #生成dt.img
#     cmake .. -DTOP_DIR=${TOP_DIR} -DPRODUCT=ascend310Brc && make device_dtb
#     cp -f dt.img ${OUTPUT_DIR}
#     echo "generate ${OUTPUT_DIR}/dt.img success!"
# }

function sign_image()
{
    image_name=$1
    tag_value=$2

    #添加256字节校验头
    python3 $SIGN_TOOL_DIR/esbc_header/esbc_header.py -raw_img $OUTPUT_DIR/$image_name -out_img $OUTPUT_DIR/starryos.bin -version $HEADER_VERSION -nvcnt 0 -tag $tag_value -platform hi1910Brc

    #添加8K校验头
    python3 $SIGN_TOOL_DIR/image_pack/image_pack.py -raw_img $OUTPUT_DIR/starryos.bin -out_img $OUTPUT_DIR/starryos.bin -platform hi1910Brc -version $HEADER_VERSION
    echo "sign ${OUTPUT_DIR}/starryos.bin success!"
}

# function gen_usrBaseConfig()
# {
#     echo "start generate usrBaseConfig.bin......."
#     cd ${TOP_DIR}/config/adaptive

#     python3 ./user_base_config/user_cfg_gen.py -in_xml adaptive_config/user_base_config.xml

#     cp -f userBaseConfig.bin ${OUTPUT_DIR}
#     echo "generate ${OUTPUT_DIR}/userBaseConfig.bin success!"
# }

# function gen_kernel_source
# {
#     echo "start generate kernel source ......."
#     #拷贝驱动编译依赖文件
#     rm -rf ${TOP_DIR}/driver/kernel/linux-4.19
#     rm -rf ${TOP_DIR}/driver/kernel/kernel/out/linux-4.19
#     cd ${TOP_DIR}/driver
#     cp ../abl ./ -rf
#     cp ../kernel/libc_sec/ ./ -rf
#     cp ../kernel/kernel/ ./ -rf
#     cp ../kernel/inc/toolchain/ inc/ -rf
#     mkdir -p abl/bbox/inc/bbox/device/
#     cp ../kernel/inc/toolchain/bbox/device abl/bbox/inc/bbox/ -rf

#     #安装Device侧的内核补丁代码：
#     cd ${TOP_DIR}/driver/kernel/kernel
#     cp kbuild/* . -rf
#     is_local=1 ./mksource.sh
#     cd ${TOP_DIR}/driver/
#     cp kernel/kernel/spmi_hisi/ kernel/ -rf
#     cp kernel/kernel/out/linux-4.19/ kernel/ -rf
#     cd kernel/linux-4.19/
#     make CROSS_COMPILE=aarch64-target-linux-gnu- ARCH=arm64 ascend310B_defconfig
#     make ARCH=arm64 CROSS_COMPILE=aarch64-target-linux-gnu- modules -j16
#     kernel_directory=$(pwd)
#     cd -
#     echo "kernel_directory is [$kernel_directory]"
#     echo "generate kernel source success!"
# }

# function make_driver()
# {
#     echo "start make driver......."
#     clean_driver

#     #拷贝驱动编译依赖文件
#     cd ${TOP_DIR}/driver
#     cp ../abl ./ -rf
#     cp ../kernel/libc_sec/ ./ -rf
#     cp ../kernel/kernel/ ./ -rf
#     cp ../kernel/inc/toolchain/ inc/ -rf
#     mkdir -p abl/bbox/inc/bbox/device/
#     cp ../kernel/inc/toolchain/bbox/device abl/bbox/inc/bbox/ -rf

#     #安装Device侧的内核补丁代码：
#     cd ${TOP_DIR}/driver/kernel/kernel
#     cp kbuild/* . -rf
#     is_local=1 ./mksource.sh
#     cd ${TOP_DIR}/driver/
#     cp kernel/kernel/spmi_hisi/ kernel/ -rf
#     cp kernel/kernel/out/linux-4.19/ kernel/ -rf

#     #生成相关配置文件
#     cd ${TOP_DIR}/driver/config/feature_config
#     grep -v "^#" ascend310Brc.config | sed 's/^CONFIG/#define CONFIG/g' > ./feature.h
#     grep -v "^#" ascend310Brc.config | sed -r 's/^(.*)=(.*)/CONFIG_DEFINES += -D\1=\2\n\1 := \2/;1iCONFIG_DEFINES :=' > ./feature.mk
#     grep -v "^#" ascend310Brc.config | sed -r 's/^(.*)=(.*)/list(APPEND CONFIG_DEFINES \1=\2)\nset(\1 \2)/;1iset(CONFIG_DEFINES)' > ./feature.cmake

#     cd ${TOP_DIR}/driver/
# 	make driver_device PRODUCT=ascend310Brc PRODUCT_SIDE=device CROSS_COMPILE=aarch64-target-linux-gnu- KERNEL_DIR=${TOP_DIR}/driver/kernel/linux-4.19/  KERNEL_DEFCONFIG=${TOP_DIR}/driver/kernel/linux-4.19/arch/arm64/configs/ascend310B_defconfig build_device=true -j16

#     mkdir -p ${OUTPUT_DIR}/driver_modules/
#     cp -rf out/release_imags/* ${OUTPUT_DIR}/driver_modules/
#     echo "generate ${OUTPUT_DIR}/driver_modules success!"
#     echo "make driver success!"
# }

# function gen_hboot2()
# {
#     echo "start generate AS310B_HBOOT2_UEFI.fd......."
#     cd ${TOP_DIR}/drivers/firmware/bios/HwPkg/scripts

#     bash builduefiAS310B.sh release AS310B ASIC DDR

#     cp -f ${TOP_DIR}/drivers/firmware/bios/output/AS310B_HBOOT2_UEFI.fd ${OUTPUT_DIR}
#     echo "generate ${OUTPUT_DIR}/AS310B_HBOOT2_UEFI.fd success!"
# }

# function clean_kernel()
# {
#     #清理内核生成的目标文件
#     rm -rf ${OUTPUT_DIR}/modules/
#     rm -rf ${OUTPUT_DIR}/kernel_modules/
#     rm -rf ${OUTPUT_DIR}/Image

#     #清理编译内核中间临时文件
#     rm -rf $KERNEL_DIR/libc_sec
#     rm -rf $KERNEL_DIR/out
# }

# function clean_driver()
# {
#     #清理编译内核中间临时文件
#     rm -rf $KERNEL_DIR/libc_sec
#     rm -rf $KERNEL_DIR/out

#     #清理驱动生成的目标文件
#     rm -rf ${OUTPUT_DIR}/driver_modules/

#     #清理编译驱动时拷贝的依赖文件
#     rm -rf ${TOP_DIR}/driver/libc_sec
#     rm -rf ${TOP_DIR}/driver/kernel
#     rm -rf ${TOP_DIR}/driver/abl
#     rm -rf ${TOP_DIR}/driver/inc/toolchain

#     #清理驱动模块编译文件
#     cd ${TOP_DIR}/driver/
#     make clean
# }

# function repack_package ()
# {
#     ${SCRIPTS_DIR}/minirc_repack.sh $1
# }

# function clean_make()
# {
#     #清理生成的目标文件
#     rm -rf ${OUTPUT_DIR}
#     #清理内核及驱动
#     clean_kernel
#     clean_driver
# }

# function do_patch_file_for_rt_kernel()
# {
#     PATCH_PATH=${KERNEL_DIR}/rtkernel_patch/
#     test -e ${PATCH_PATH}/series.conf || exit 1
#     dos2unix ${PATCH_PATH}/series.conf
#     while read line || [[ -n "${line}" ]]
#     do
#         file=$(echo $line)
#         echo $file
#         test -e ${PATCH_PATH}/${file} || exit 1
#         cd ${KERNEL_DIR}/out/rt_kernel/ && git apply --whitespace=nowarn ${PATCH_PATH}/${file} || exit 1; cd -
#     done < ${PATCH_PATH}/series.conf
# }
 
# function gen_rt_kernel_image()
# {   
#     echo "start make kernel......."
#     rt_kernel_name="kernel-rt-source-5.10.0-136.12.0.rt62.59.oe2203sp1.aarch64"
#     #清除编译缓存
#     cd $KERNEL_DIR
#     rm -rf out
#     rm -rf usr
 
#     #解压rt-kernel包
#     if [ -e "${TOP_DIR}/${rt_kernel_name}.rpm" ]; then
#         cd ${TOP_DIR} && rpm2cpio ${TOP_DIR}/${rt_kernel_name}.rpm | cpio -id && cd -
#     else
#         echo "The rt-kernel file does not exist, please check."
#         return
#     fi
#     mkdir ${KERNEL_DIR}/out && mv ${TOP_DIR}/usr/src/linux-5.10.0-136.12.0.rt62.59.oe2203sp1.aarch64 ${KERNEL_DIR}/out/rt_kernel
#     rm -rf ${TOP_DIR}/usr
    
#     #打内核补丁
#     do_patch_file_for_rt_kernel
#     echo "+" > "${KERNEL_DIR}/out/rt_kernel/localversion"
 
#     #内核编译依赖
#     cp -r ../../libc_sec .
#     cp -r spmi_hisi out
#     cp publickey/ELF_Common_RSA4096_CN_20191009_Huawei.der out/rt_kernel/certs/ELF_Common_RSA4096_CN_20191009_Huawei.der
 
#     cd out/rt_kernel
#     #生成内核配置
#     make ARCH=arm64 CROSS_COMPILE=aarch64-target-linux-gnu- ascend310B_defconfig
#     #支持用户自定义内核配置选项，交互式弹出菜单选项
#     make ARCH=arm64 CROSS_COMPILE=aarch64-target-linux-gnu- menuconfig
 
#     #编译内核
#     make ARCH=arm64 CROSS_COMPILE=aarch64-target-linux-gnu- Image -j16
#     make ARCH=arm64 CROSS_COMPILE=aarch64-target-linux-gnu- modules -j16
#     make ARCH=arm64 CROSS_COMPILE=aarch64-target-linux-gnu- INSTALL_MOD_PATH=$OUTPUT_DIR/rt_modules modules_install
#     mkdir -p $OUTPUT_DIR/rt_kernel_modules
#     find $OUTPUT_DIR/rt_modules/ -name *.ko -exec cp -a {} $OUTPUT_DIR/rt_kernel_modules \;
 
#     cp -f ${KERNEL_DIR}/out/rt_kernel/arch/arm64/boot/Image $OUTPUT_DIR
#     echo "generate ${OUTPUT_DIR}/rt_kernel_modules success!"
#     echo "generate ${OUTPUT_DIR}/Image success!"
 
#     #签名
#     sign_image Image uimage
# }

function flash_image() {
    # 列出所有可用的 sd 设备（主设备，排除分区如 sda1、sdb2 等）
    echo "正在检测可用设备（/dev/sd*）..."
    echo "====================================="
    # 使用 lsblk 过滤主设备，排除分区（名称不含数字），并获取名称和容量
    devices=()
    capacities=()
    # 读取设备信息，包括名称和容量
    while read -r name type size; do
        devices+=("/dev/$name")
        capacities+=("$size")
    done < <(lsblk -n -o NAME,TYPE,SIZE | grep -E '^sd[a-z] +disk')

    # 检查是否有可用设备
    if [ ${#devices[@]} -eq 0 ]; then
    echo "未检测到可用设备（/dev/sd*），请检查设备连接后重试。"
    exit 1
    fi

    # 显示设备列表并编号，包括容量信息
    echo "可用设备列表（容量 < 100G）："
    echo "====================================="
    for i in "${!devices[@]}"; do
        # 检查设备容量是否小于100G
        device_size="${capacities[$i]}"
        device_num="${device_size%[A-Za-z]*}"  # 提取数字部分
        device_unit="${device_size##*[0-9.]}"  # 提取单位部分
        
        # 转换为GB进行比较
        case $device_unit in
            B) device_gb=$(echo "scale=2; $device_num / 1024 / 1024 / 1024" | bc);;
            K) device_gb=$(echo "scale=2; $device_num / 1024 / 1024" | bc);;
            M) device_gb=$(echo "scale=2; $device_num / 1024" | bc);;
            G) device_gb=$device_num;;
            T) device_gb=$(echo "scale=2; $device_num * 1024" | bc);;
            *) device_gb=0;; # 未知单位，默认为0GB
        esac
        
        # 只显示小于100G的设备
        if (( $(echo "$device_gb < 100" | bc -l) )); then
            echo "[$((i+1))] ${devices[$i]} (容量: ${capacities[$i]})"
        fi
    done
    echo "====================================="

    # 让用户输入数字选择设备
    read -p "请输入要操作的设备编号（1-${#devices[@]}）：" num

    # 验证输入是否为有效数字
    if ! [[ "$num" =~ ^[0-9]+$ ]] || [ "$num" -lt 1 ] || [ "$num" -gt ${#devices[@]} ]; then
    echo "输入无效！请输入 1 到 ${#devices[@]} 之间的数字。"
    exit 1
    fi

    # 获取用户选择的设备
    TARGET_DEVICE="${devices[$((num-1))]}"
    TARGET_CAPACITY="${capacities[$((num-1))]}"
    
    # 检查设备容量是否小于100G
    device_num="${TARGET_CAPACITY%[A-Za-z]*}"
    device_unit="${TARGET_CAPACITY##*[0-9.]}"
    
    # 转换为GB进行比较
    case $device_unit in
        B) device_gb=$(echo "scale=2; $device_num / 1024 / 1024 / 1024" | bc);;
        K) device_gb=$(echo "scale=2; $device_num / 1024 / 1024" | bc);;
        M) device_gb=$(echo "scale=2; $device_num / 1024" | bc);;
        G) device_gb=$device_num;;
        T) device_gb=$(echo "scale=2; $device_num * 1024" | bc);;
        *) device_gb=0;; # 未知单位，默认为0GB
    esac
    
    if (( $(echo "$device_gb >= 100" | bc -l) )); then
        echo "错误：不允许选择容量大于等于100G的设备。请选择较小的设备。"
        exit 1
    fi

    # 二次确认（显示设备详情，增强警惕）
    echo "====================================="
    echo "你选择的设备是：$TARGET_DEVICE (容量: $TARGET_CAPACITY)"
    lsblk "$TARGET_DEVICE"  # 显示设备分区信息，帮助用户确认
    echo "====================================="
    read -p "警告：此操作会覆盖 $TARGET_DEVICE 上的所有数据！确认继续？[y/N] " confirm

    if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
    echo "开始写入..."
    sudo dd if="../../starryos.bin" of="$TARGET_DEVICE" seek=32768 bs=512
    echo "操作完成。"
    else
    echo "操作已取消。"
    exit 0
    fi
}

if [ $# -lt 1 ]; then
	usage
fi

# if [ ! -d ${OUTPUT_DIR} ]; then
# 	mkdir -p ${OUTPUT_DIR}
# fi

case $1 in
	"clean")
        clean_make
		;;
	"kernel")
        gen_kernel_image
        sign_image Image uimage
		;;
	"starryos")
        kernel_name=$(ls $OUTPUT_DIR/*aarch64-opi-aipro.bin | xargs basename)
		sign_image $kernel_name uimage
		# flash_image starryos.bin
		# sync
		;;
	"flash_sd")
		# sudo dd if=$OUTPUT_DIR/$2 of=/dev/sdb seek=32768 bs=512
		sync
		;;
	"dtb")
        gen_dtimage
        sign_image dt.img dtimg
		;;
	"usrBaseConfig")
        gen_usrBaseConfig
        sign_image userBaseConfig.bin userbasecfg
		;;
    "hboot2")
        gen_hboot2
        sign_image AS310B_HBOOT2_UEFI.fd hboot2
		;;
	"driver")
        make_driver
        ;;
    "kernelSource")
        gen_kernel_source
        ;;
	"repack")
        repack_package $2
        ;;
    "rtKernel")
        gen_rt_kernel_image
		;;
    "test")
        echo $TOP_DIR
        echo $OUTPUT_DIR
        ;;
	*)
	usage
	;;
esac


